package com.sirun.ble.services;


import static com.sirun.ble.constants.BleConfig.BleSdkTag;
import static com.sirun.ble.constants.BleConfig.CMD_TYPE_DEFAULT;
import static com.sirun.ble.constants.BleConfig.CMD_TYPE_FIND_CAR;
import static com.sirun.ble.constants.BleConfig.CMD_TYPE_LOCK;
import static com.sirun.ble.constants.BleConfig.CMD_TYPE_UNLOCK;
import static com.sirun.ble.constants.BleConfig.CONTROL_STEP_CMD_SEND;
import static com.sirun.ble.constants.BleConfig.CONTROL_STEP_FAIL;
import static com.sirun.ble.constants.BleConfig.CURRENT_CMD_TYPE;
import static com.sirun.ble.constants.BleConfig.TAG_CONNECTED;
import static com.sirun.ble.constants.BleConfig.TAG_CONNECTED_AUTH;
import static com.sirun.ble.constants.BleConfig.TAG_CONNECTED_NONE;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;

import com.sirun.ble.IMyAidlInterface;
import com.sirun.ble.enums.BleEnum;
import com.sirun.ble.listeners.OnBleConnectListener;
import com.sirun.ble.listeners.OnBleControlListener;
import com.sirun.ble.listeners.OnBleDownloadListener;
import com.sirun.ble.listeners.OnBleRssiListener;
import com.sirun.ble.listeners.OnBleScanListener;
import com.sirun.ble.listeners.OnBleSpareListener;
import com.sirun.ble.listeners.OnBleVehicleStatusListener;
import com.sirun.ble.utils.AwByteUtil;
import com.sirun.ble.utils.AwDataUtil;
import com.sirun.ble.utils.AwLog;
import com.sirun.ble.utils.sdk.AwBleCallbackUtil;
import com.sirun.ble.utils.sdk.AwBleRssiUtil;
import com.sirun.ble.utils.sdk.AwBleSpUtil;
import com.sirun.ble.utils.sdk.AwBleUtil;
import com.sirun.ble.utils.sdk.WulingBleCmdUtil;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * @author : hzw
 */
@SuppressLint("MissingPermission")
public class BleService extends Service {

    private static final String TAG = "SERVICE";
    private static final int DEFALUT_COUNTDOWN_TIME = 20000;
    private UUID UUID_SERVICE = null; //Common Service
    private UUID UUID_WRITE = null;
    private UUID UUID_NOTIFY = null;
    private Context mContext = BleService.this;
    public boolean isScanning = false;
    public boolean isConnected = false;
    private BluetoothGatt mBluetoothGatt;
    private Handler mHandler = new Handler();
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothLeScanner mBluetoothLeScanner;

    private OnBleConnectListener mBleConnectListener;
    private OnBleScanListener mBleScanListener;
    private OnBleDownloadListener mBleDownloadListener;
    private OnBleSpareListener mBleSpareListener;
    private OnBleRssiListener mBleRssiListener;
    private OnBleControlListener mBleControlListener;
    private OnBleVehicleStatusListener mBleVehicleStatusListener;

    private BluetoothDevice mBluetoothDevice;
    private MyCountTime mCountTime;
    private final ScanCallback mBleScanCallback = new MyScanCallback();
    private boolean isAuth = false;
    private boolean isRetry = false;
    private boolean isDiscovery = false;
    private boolean isNotifySuccess = false;
    private int authCount = 0;
    private boolean isDisConnecting = false;
    private int calCount = 0;
    private int totalRssi = 0;
    private long lastTime = 0;
    public BluetoothGattCallback mBluetoothGattCallback = new MyBluetoothGattCallback();

    public class MyBinder extends IMyAidlInterface.Stub {

        @Override
        public String getName() throws RemoteException {
            return BleService.class.getName();
        }
    }

    public MyBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        CURRENT_CMD_TYPE = CMD_TYPE_DEFAULT;
        initBleAdapterAndScanner();
    }

    public void setContext(Context context) {
        this.mContext = context;
    }

    private void initBleAdapterAndScanner() {
        if(mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        if(mBluetoothLeScanner == null) {
            mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        }
    }

    public boolean isAuthConnected() {
        return isConnected && isAuth;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeConnect(false);
        if(mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
    }

    public void setConnectListener(OnBleConnectListener bleConnectListener) {
        mBleConnectListener = bleConnectListener;
        if(mBleConnectListener == null) {
            AwLog.d(TAG,"setConnectListener", "bleservice set connectlistener is null");
        } else {
            AwLog.d(TAG, "setConnectListener", "bleservice set connectlistener != null");
        }
    }

    public void setScanListener(OnBleScanListener bleScanListener) {
        mBleScanListener = bleScanListener;
    }

    public void setDownloadListener(OnBleDownloadListener bleDownloadListener) {
        mBleDownloadListener = bleDownloadListener;
    }

    public void setSpareListener(OnBleSpareListener bleSpareListener) {
        mBleSpareListener = bleSpareListener;
    }

    public void setBleRssiListener(OnBleRssiListener bleRssiListener) {
        mBleRssiListener = bleRssiListener;
    }


    public void setControlListener(OnBleControlListener bleControlListener) {
        mBleControlListener = bleControlListener;
    }

    public void setCarStatusListener(OnBleVehicleStatusListener bleVehicleStatusListener) {
        mBleVehicleStatusListener = bleVehicleStatusListener;
    }

    public void startScanBle() {
        if(mBluetoothLeScanner == null) {
            AwLog.d(TAG, "startScanBle", "startScanBle bluetoothLeScanner is null, delay and retry");
            mHandler.postDelayed(new ScanRunnable(), 2000);
            return;
        }
        if(isDisConnecting) {
            AwLog.d(TAG, "startScanBle", "startScanBle, However, isDisConnecting true, , delay and retry");
            mHandler.postDelayed(new ScanRunnable2(), 1000);
            return;
        }
        AwLog.d(TAG, "startScanBle", "pre checked passed...");
        mHandler.postDelayed(new ScanRunnable3(), AwBleUtil.getIntervalTime(mContext));
    }

    public class ScanRunnable implements Runnable {
        @Override
        public void run() {
            initBleAdapterAndScanner();
            startScanBle();
            AwLog.d(TAG, "ScanRunnable", "...");
        }
    }

    public class ScanRunnable2 implements Runnable {
        @Override
        public void run() {
            startScanBle();
            AwLog.d(TAG, "ScanRunnable2", "...");
        }
    }

    public class ScanRunnable3 implements Runnable {
        @Override
        public void run() {
            startScanCountDown();
            AwLog.d(TAG, "ScanRunnable3", "...");
        }
    }


    private void startScanCountDown() {
        if(isScanning) {
            AwLog.d(TAG, "startScanCountDown", "isScanning. cancel and retry startScanCountDown, return.");
            cancelScanCountdown();
            mHandler.postDelayed(new ScanRunnable3(), 2000);
            return;
        }
        AwLog.d(TAG, "startScanCountDown", "pre check passed...");
        if(mCountTime == null) {
            mCountTime = new MyCountTime(DEFALUT_COUNTDOWN_TIME, 1000);
        }
        isScanning = true;
        mCountTime.start();
        mBluetoothLeScanner.startScan(mBleScanCallback);
    }

    private void cancelScanCountdown() {
        AwLog.d(TAG, "cancelScanCountdown", "...");
        if(mCountTime != null) {
            mCountTime.cancel();
            mCountTime = null;
            isScanning = false;
        }
        stopScanBle();//停止扫描
    }

    public void reScanBle() {
        AwLog.d(TAG, "reScanBle", "...");
        startScanBle();
    }

    public void stopScanBle() {
        if(mBluetoothLeScanner == null) {
            AwLog.d(TAG, "stopScanBle", "mBluetoothLeScanner is null");
            return;
        }
        AwLog.d(TAG, "stopScanBle", "...");
        try {
            mBluetoothLeScanner.stopScan(mBleScanCallback);
        } catch (Exception e) {
            e.printStackTrace();
            AwLog.d(TAG, "stopScanBle", "exception, e: " + e.getMessage());
        }
    }

    public void connectBle(BluetoothDevice dev) {
        AwLog.d(TAG, "connectBle", "dev: " + dev.toString());
//        closeConnect(false);
        mBluetoothGatt = dev.connectGatt(mContext, false, mBluetoothGattCallback);
        mBluetoothGatt.connect();
    }

    // BLE中心设备连接外围设备的数量有限(大概2~7个)，在建立新连接之前必须释放旧连接资源，否则容易出现连接错误133
    public void closeConnect(boolean needCallback) {
        if(isDisConnecting) {
            AwLog.d(TAG, "closeConnect", "isDisConnecting true, return");
            return;
        }
        AwLog.d(TAG, "closeConnect", "...");
        try {
            cancelScanCountdown();
            if (mBluetoothGatt != null) {
                mBluetoothGatt.disconnect();
                mBluetoothGatt.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            AwLog.d(TAG, "closeConnect", "Exception e: " + e.getMessage());
        }
        if(needCallback) {
            if(mBleConnectListener == null) {
                AwLog.d(TAG, "closeConnect", "BleConnectListener is null");
                return;
            }
            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_CLOSE, TAG_CONNECTED_NONE, mBluetoothDevice);
        }
        isConnected = false;
        isAuth = false;
        isDisConnecting = true;
        isDiscovery = false;
        isNotifySuccess = false;
        mHandler.postDelayed(new CloseConnectRunnable(), 2000);
    }

    public class CloseConnectRunnable implements Runnable {

        @Override
        public void run() {
            AwLog.d(TAG, "CloseConnectRunnable", "...");
            AwBleSpUtil.setBleDisconnectTime(mContext, String.valueOf(System.currentTimeMillis()));
            isDisConnecting = false;
        }
    }

    // 获取Gatt服务
    private BluetoothGattService getGattService(UUID uuid) {
        if (!isConnected) {
            AwLog.d(TAG,  "getGattService", "no connect");
            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NONE, TAG_CONNECTED_NONE, mBluetoothDevice);
            return null;
        }
        if(uuid == null) {
            AwLog.d(TAG, "getGattService","uid is null");
            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NO_SERVICE, TAG_CONNECTED_NONE, mBluetoothDevice);
            return null;
        }
        BluetoothGattService service = mBluetoothGatt.getService(uuid);
        if (service == null) {
            closeConnect(true);
            AwLog.d(TAG, "getGattService","findServiceByid, service is null, UUID = " + uuid);
            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NO_SERVICE, TAG_CONNECTED_NONE, mBluetoothDevice);
        }
        return service;
    }

    // 设置通知Characteristic变化会回调->onCharacteristicChanged()
    private boolean setNotify() {
        AwLog.d(TAG, "setNotify","UUID_SERVICE: " + UUID_SERVICE);
        BluetoothGattService service = getGattService(UUID_SERVICE);
        if (service != null) {
            //特征通知订阅
//            BluetoothGattCharacteristic writeCharacteristic = service.getCharacteristic(UUID_WRITE);
//            if(writeCharacteristic == null) {
//                AwLog.d(TAG, "setNotify","writeCharacteristic is null");
//                return false;
//            }
//            isNotifySuccess = mBluetoothGatt.setCharacteristicNotification(writeCharacteristic, true);
//            AwLog.d(TAG, "setNotify","writeCharacteristic result: " + writeCharacteristic);
//            if(isNotifySuccess) {
//                List<BluetoothGattDescriptor> tempList = writeCharacteristic.getDescriptors();
//                for(BluetoothGattDescriptor descriptor : tempList) {
//                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
//                    boolean writeResult = mBluetoothGatt.writeDescriptor(descriptor);
//                    AwLog.d(TAG, "setNotify","writeCharacteristic descriptor: " + descriptor.getUuid() + " ,writeResult: " + writeResult);
//                }
//            }
            //特征通知订阅
            BluetoothGattCharacteristic nofifyCharacteristic = service.getCharacteristic(UUID_NOTIFY);
            if(nofifyCharacteristic == null) {
                AwLog.d(TAG, "setNotify","nofifyCharacteristic is null");
                return false;
            }
            if(mBluetoothGatt == null) {
                AwLog.d(TAG, "setNotify","mBluetoothGatt is null");
                return false;
            }
            isNotifySuccess = mBluetoothGatt.setCharacteristicNotification(nofifyCharacteristic, true);
            AwLog.d(TAG, "setNotify","nofifyCharacteristic result: " + isNotifySuccess);
            if(isNotifySuccess) {
                List<BluetoothGattDescriptor> tempList = nofifyCharacteristic.getDescriptors();
                for(BluetoothGattDescriptor descriptor : tempList) {
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    boolean writeResult = mBluetoothGatt.writeDescriptor(descriptor);
                    AwLog.d(TAG, "setNotify","nofifyCharacteristic descriptor: " + descriptor.getUuid() + " ,writeResult: " + writeResult);
                }
            }
            if(isNotifySuccess) {
                AwLog.d(TAG, "setNotify", "通知设置成功...监听蓝牙反馈信息中....");
            } else {
                AwLog.d(TAG, "setNotify", "通知设置失败");
                AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NOTIFY_FAIL, TAG_CONNECTED, mBluetoothDevice);
                closeConnect(true);
            }
            return isNotifySuccess;
        } else {
            AwLog.d(TAG, "setNotify", "BluetoothGattService is null");
            return false;
        }
    }

    private void handleDiscoveryGattService(BluetoothGatt gatt) {
        if(isNotifySuccess) {
            AwLog.d(TAG, "handleDiscoveryGattService","isNotifySuccess return.");
            return;
        }
        if (gatt == null) {
            AwLog.d(TAG, "handleDiscoveryGattService","BluetoothGatt is null, return.");
            return;
        }
        List<BluetoothGattService> list = gatt.getServices();
        if(AwDataUtil.isEmpty(list)) {
            AwLog.d(TAG, "handleDiscoveryGattService", "gatt.getServices is null, return.");
            return;
        }
        for(BluetoothGattService service : list) {
            AwLog.d(TAG, "handleDiscoveryGattService", "serviceUUID: " + service.getUuid());
            if(service.getUuid().toString().contains("182a")) {
                UUID_SERVICE = service.getUuid();
                List<BluetoothGattCharacteristic> subList = service.getCharacteristics();
                for(BluetoothGattCharacteristic subTemp : subList) {
                    AwLog.d(TAG, "handleDiscoveryGattService", "discovery uuid characteristic uuid..." + subTemp.getUuid());
//                    if(subTemp.getUuid().toString().contains("aa01")) {
//                        UUID_WRITE = subTemp.getUuid();
//                        AwLog.d(TAG, "handleDiscoveryGattService", "UUID_WRITE..." + UUID_WRITE);
//                    } else if(subTemp.getUuid().toString().contains("aa02")) {
//                        UUID_NOTIFY = subTemp.getUuid();
//                        AwLog.d(TAG, "handleDiscoveryGattService", "UUID_NOTIFY..." + UUID_NOTIFY);
//                    }
                    if(subTemp.getUuid().toString().contains("2a7f")) {
                        UUID_NOTIFY = subTemp.getUuid();
                        AwLog.d(TAG, "handleDiscoveryGattService", "UUID_NOTIFY..." + UUID_NOTIFY);
                    }
                }
                setNotify();
                AwLog.d(TAG, "handleDiscoveryGattService","Connect discovery uuid 2A7F...");
            }
        }
        mHandler.postDelayed(() -> {
            AwLog.d(TAG, "handleDiscoveryGattService","requestMtu: 128");
            gatt.requestMtu(128);
        }, 500);
    }

    public class MyCountTime extends CountDownTimer {

        public MyCountTime(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onFinish() {
            if(isScanning) {
                stopScanBle();
                AwLog.d(TAG, "MyCountTime", "onFinish stopScan, The specified Bluetooth device was not found");
                AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NONE_SEARCH_DEVICE, TAG_CONNECTED_NONE, mBluetoothDevice);
            }
        }

        @Override
        public void onTick(long millisUntilFinished) {
        }
    }

    public class MyScanCallback extends ScanCallback {

        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            // Android5.0新增的扫描API，扫描返回的结果更友好，比如BLE广播数据以前是byte[] scanRecord，而新API帮我们解析成ScanRecord类
            if(!AwDataUtil.isEmpty(result.getDevice().getName())) {
                AwLog.d(TAG, "ScanCallback", "onScanResult device name: " + result.getDevice().getName() + " ,address: " + result.getDevice().getAddress()) ;
                if(result.getDevice().getName().equals(AwBleSpUtil.getBleName(mContext))) {
                    mBluetoothDevice = result.getDevice();
                    stopScanBle();
                    AwLog.d(TAG, "ScanCallback","to connect device info: "  + mBluetoothDevice.toString());
                    toConnect();
                }
            } else {
//                AwLog.d(TAG, "ScanCallback", "onScanResult device name is null and address: " + result.getDevice().getAddress());
            }
        }
    }

    private void toConnect() {
        if(mBluetoothDevice == null) {
            AwLog.d(TAG, "toConnect","BluetoothDevice is null...return.");
            return;
        }
        AwLog.d(TAG, "toConnect", "device info: " + mBluetoothDevice.getName() + " ,address: " + mBluetoothDevice.getAddress());
        cancelScanCountdown();
        connectBle(mBluetoothDevice);
    }

    public void reConnectBle() {
        if(isDisConnecting) {
            AwLog.d(TAG, "reConnectBle", "isDisConnecting, so delay reConnect...");
            mHandler.postDelayed(new ReConnectRunnable(), 3000);
            return;
        }
        AwLog.d(TAG, "reConnectBle", "...");
        mHandler.postDelayed(new ReConnectRunnable2(), 2000);
    }

    public class ReConnectRunnable implements Runnable {

        @Override
        public void run() {
            reConnectBle();
        }
    }

    public class ReConnectRunnable2 implements Runnable {

        @Override
        public void run() {
            isRetry = true;
            connectBle(mBluetoothDevice);
        }
    }

    public void controlCarByBle(int cmdType) {
        if(!isConnected) {
            CURRENT_CMD_TYPE = CMD_TYPE_DEFAULT;
            AwBleCallbackUtil.controlCallback(mBleControlListener, BleEnum.BLE_CONNECT_NONE, cmdType, CONTROL_STEP_FAIL, null);
            return;
        }
//        if(!isAuth) {
//            CURRENT_CMD_TYPE = CMD_TYPE_DEFAULT;
//            closeConnect(true);
//            AwBleCallbackUtil.controlCallback(mBleControlListener, BleEnum.BLE_CONNECT_AUTH_FAIL, cmdType, CONTROL_STEP_FAIL, null);
//            return;
//        }
        AwLog.d(BleSdkTag, "controlCarByBle cmdType: " + cmdType);
        BluetoothGattService service = getGattService(UUID_SERVICE);
        if (service != null) {
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_WRITE);
            switch (cmdType) {
                case CMD_TYPE_UNLOCK:
//                    BleLog.dN(BleSdkTag, "send control unlock...");
                    CURRENT_CMD_TYPE = CMD_TYPE_UNLOCK;
                    characteristic.setValue(WulingBleCmdUtil.getEncryptLockCmd(false));
                    break;
                case CMD_TYPE_LOCK:
//                    BleLog.dN(BleSdkTag, "control lock...");
                    CURRENT_CMD_TYPE = CMD_TYPE_LOCK;
                    characteristic.setValue(WulingBleCmdUtil.getEncryptLockCmd(true));
                    break;
                case CMD_TYPE_FIND_CAR:
//                    BleLog.dN(BleSdkTag, "service control find...");
                    CURRENT_CMD_TYPE = CMD_TYPE_FIND_CAR;
                    break;
            }
            mBluetoothGatt.writeCharacteristic(characteristic);
            AwLog.d(BleSdkTag, "controlCarByBle...write success");
            if(mBleControlListener == null) {
                AwLog.d(BleSdkTag, "controlCarByBle mBleControlListener is null");
                return;
            }
            AwBleCallbackUtil.controlCallback(mBleControlListener, null, CURRENT_CMD_TYPE, CONTROL_STEP_CMD_SEND, null);
        } else {
            closeConnect(true);
            AwLog.d(BleSdkTag, "controlCarByBle BluetoothGattService is null");
            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NO_SERVICE, TAG_CONNECTED_NONE, mBluetoothDevice);
            AwBleCallbackUtil.controlCallback(mBleControlListener, BleEnum.BLE_CONTROL_FAIL, CURRENT_CMD_TYPE, CONTROL_STEP_FAIL, null);
        }
    }

    public class MyBluetoothGattCallback extends BluetoothGattCallback {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
//            callbackCurrentBleDevice(gatt);
//            mBluetoothDevice = gatt.getDevice();
            AwLog.d(TAG, "GattCallback", String.format("onConnectionStateChange: %s,%s,%s,%s", mBluetoothDevice.getName(), mBluetoothDevice.getAddress(), status, newState));
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
                isConnected = true;
                isDiscovery = gatt.discoverServices(); //启动服务发现
                AwLog.d(TAG, "GattCallback","onConnectionStateChange, discoverServices: " + isDiscovery);
                boolean rssiStatus = mBluetoothGatt.readRemoteRssi();
                AwLog.d(TAG, "GattCallback","onConnectionStateChange, readRemoteRssi: " + rssiStatus);
            } else {
                AwLog.d(TAG, "GattCallback","onConnectionStateChange, close connect");
                isConnected = false;
                closeConnect(false);
            }
            if(mBleConnectListener != null) {
                if(status == 0) {
                    if(newState == 2) {
                        AwLog.d(TAG, "GattCallback","onConnectionStateChange newState=2, " + String.format("belservice [%s] connected", mBluetoothDevice));
                        AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_SUCCESS, isAuth ? TAG_CONNECTED_AUTH : TAG_CONNECTED, mBluetoothDevice);
                    } else {
                        AwLog.d(TAG, "GattCallback","onConnectionStateChange newState!=2, " + String.format("belservice [%s] disConnected", mBluetoothDevice));
                        AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_FAIL, TAG_CONNECTED_NONE, mBluetoothDevice);
                    }
                } else {
                    AwLog.d(TAG, "GattCallback","onConnectionStateChange status!=0, " + String.format("belservice [%s] connect error", status));
                    if(status == 8) {
                        AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_FAIL_DISTANCE, TAG_CONNECTED_NONE, mBluetoothDevice);
                    } else if(status == 19) {
                        AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_FAIL_LATER_RETRY, TAG_CONNECTED_NONE, mBluetoothDevice);
                    } else {
                        if(!isRetry){
                            AwLog.d(TAG, "GattCallback","onConnectionStateChange status !=0, retry connect dalay");
                            reConnectBle();
                            return;
                        }
                        AwLog.d(TAG, "GattCallback","onConnectionStateChange connect fail, status is " + status + " and retry fail.");
                        if(status == 133) {
                            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_FAIL_FREQUENTLY, TAG_CONNECTED_NONE, mBluetoothDevice);
                        } else {
                            AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_FAIL, TAG_CONNECTED_NONE, mBluetoothDevice);
                        }
                    }
                }
            } else {
                AwLog.d(TAG, "GattCallback","onConnectionStateChange ConnectCallback is null");
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            AwLog.d(TAG, "GattCallback", String.format("onServicesDiscovered: %s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), status));

            //BLE服务发现不成功
            if(status != BluetoothGatt.GATT_SUCCESS) {
                AwLog.d(TAG, "GattCallback","服务发现失败...断开连接");
                closeConnect(false);
                AwBleCallbackUtil.connectCallback(mBleConnectListener, BleEnum.BLE_CONNECT_NO_SERVICE, TAG_CONNECTED_NONE, mBluetoothDevice);
                return;
            }
            handleDiscoveryGattService(gatt);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            AwLog.d(TAG, "GattCallback","onMtuChanged: " + mtu);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            UUID uuid = characteristic.getUuid();
            String valueStr = AwByteUtil.printBytes(characteristic.getValue());
            AwLog.d(TAG, "GattCallback", String.format("onCharacteristicRead: %s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
            if(mBleSpareListener != null) {
                mBleSpareListener.onCharacteristicRead("belservice read Characteristic[" + uuid + "]:\n" + valueStr);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//            callbackCurrentBleDevice(gatt);
            UUID uuid = characteristic.getUuid();
            String valueStr = AwByteUtil.printBytes(characteristic.getValue());

            AwLog.d(TAG, "GattCallback", String.format("onCharacteristicWrite: %s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
            if(mBleSpareListener != null) {
                mBleSpareListener.onCharacteristicWrite("belservice write Characteristic[" + uuid + "]:\n" + valueStr);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //下面2个方法都可正常打印
//            BleLog.dN(TAG, "onCharacteristicChanged value printByte: " + BleByteUtil.printByte(characteristic.getValue()));
//            BleLog.dN(TAG, "onCharacteristicChanged value: " + BleByteUtil.bytesToHexString(characteristic.getValue()));
            UUID uuid = characteristic.getUuid();
            String valueStr = AwByteUtil.printBytes(characteristic.getValue());
            AwLog.d(TAG, "GattCallback", String.format("onCharacteristicChanged: %s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr));
            if(mBleSpareListener != null) {
                mBleSpareListener.onCharacteristicChanged("belservice notify Characteristic[" + uuid + "]:\n" + valueStr);
            }
//            if(System.currentTimeMillis() - lastTime < 1000) {
//                AwLog.d(TAG,"===>间隔时间过段, 拦截下...");
//                return;
//            }
//            lastTime = System.currentTimeMillis();
            int resultRssi = characteristic.getValue()[10] & 0xFF;
            if(calCount < 10) {
                calCount++;
                totalRssi = resultRssi + totalRssi;
            } else {
                if(mBleRssiListener != null) {
                    AwLog.d(TAG,"===>回调平均值RSSI: " + (totalRssi / 10) + " ,totalRssi: " + totalRssi + " ,calCount: " + calCount);
                    mBleRssiListener.getRssi(totalRssi / 10);
                }
                calCount = 0;
                totalRssi = 0;
            }
            if(mBleRssiListener != null) {
                AwLog.d(TAG,"===>回调每个值RSSI: " + valueStr);
                mBleRssiListener.getRssiEvery(valueStr);
            }
            AwLog.d(TAG,"===>RSSI: " + resultRssi + " ,totalRssi: " + totalRssi + " ,calCount: " + calCount);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
//            callbackCurrentBleDevice(gatt);
            UUID uuid = descriptor.getUuid();
            String valueStr = Arrays.toString(descriptor.getValue());
            AwLog.d(TAG, "GattCallback", String.format("onDescriptorRead: %s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
            if(mBleSpareListener != null) {
                mBleSpareListener.onDescriptorRead("belservice read Descriptor[" + uuid + "]:\n" + valueStr);
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
//            callbackCurrentBleDevice(gatt);
            UUID uuid = descriptor.getUuid();
            String valueStr = Arrays.toString(descriptor.getValue());

            AwLog.d(TAG, "GattCallback", String.format("onDescriptorWrite: %s,%s,%s,%s,%s", gatt.getDevice().getName(), gatt.getDevice().getAddress(), uuid, valueStr, status));
            if(mBleSpareListener != null) {
                mBleSpareListener.onDescriptorWrite("belservice write Descriptor[" + uuid + "]:\n" + valueStr);
            }
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
            AwLog.d(TAG, "GattCallback","onReadRemoteRssi rssi: " + rssi);
            if(mBleSpareListener != null && status == BluetoothGatt.GATT_SUCCESS) {
                mBleSpareListener.getRssi(rssi, AwBleRssiUtil.getDistance(rssi));
            }
        }
    }

}
